package com.logos.ruralrevitalization.utils;

import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTValidator;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.logos.ruralrevitalization.exception.UnauthorizedException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.Duration;
import java.util.Date;

@Component
@Slf4j
@ConditionalOnProperty(prefix = "rural.jwt", name = "enabled", havingValue = "true")
public class JwtPlusTool {

    // 配置文件中的密钥
    @Value("${rural.jwt.key}")
    private String key;

    // JWT 签名器
    private JWTSigner jwtSigner;

    /**
     * 初始化 JWT 签名器
     */
    @PostConstruct
    public void init() {
        if (key == null || key.isEmpty()) {
            throw new IllegalArgumentException("JWT 密钥不能为空，请检查配置文件");
        }
        this.jwtSigner = JWTSignerUtil.createSigner("HS256", key.getBytes());
        log.info("JWT 密钥已加载: {}", key);
    }

    /**
     * 创建 JWT Token
     *
     * @param userId 用户标识（如用户 ID 或用户名）
     * @param ttl    Token 的有效期
     * @return 生成的 JWT Token 字符串
     */
    public String createToken(String userId, Duration ttl) {
        long issuedAt = System.currentTimeMillis();
        long expiresAt = issuedAt + ttl.toMillis();

        log.info("Creating token with issued-at: {}, expires-at: {}", issuedAt, expiresAt);

        return JWT.create()
                .setPayload("user-id", userId)
                .setPayload("issued-at", String.valueOf(issuedAt)) // 添加签发时间戳
                .setExpiresAt(new Date(expiresAt)) // 设置过期时间
                .setSigner(jwtSigner)
                .sign();
    }

    /**
     * 解析 JWT Token
     *
     * @param token 待解析的 JWT Token 字符串
     * @return 解析后的用户标识（如用户 ID）
     * @throws UnauthorizedException 如果 Token 无效或过期
     */
    public String parseToken(String token) {
        if (token == null || token.isEmpty()) {
            throw new UnauthorizedException("未登录");
        }

        try {
            JWT jwt = JWT.of(token).setSigner(jwtSigner);

            // 记录 Token 的相关信息
            log.info("Token issued-at: {}, expires-at: {}, current time: {}",
                    jwt.getPayload("issued-at"), jwt.getPayload("exp"), System.currentTimeMillis());

            // 验证签名
            if (!jwt.verify()) {
                log.error("JWT 签名验证失败: {}", token);
                throw new UnauthorizedException("无效的 Token");
            }

            // 验证 Token 是否过期
            JWTValidator.of(jwt).validateDate();

            // 获取用户标识
            Object userPayload = jwt.getPayload("user-id");
            if (userPayload == null) {
                throw new UnauthorizedException("无效的 Token");
            }

            log.info("JWT Token 解析成功: {}", token);
            return userPayload.toString();
        } catch (ValidateException e) {
            log.error("JWT Token 已过期: {}", e.getMessage());
            throw new UnauthorizedException("Token 已过期");
        } catch (RuntimeException e) {
            log.error("JWT Token 解析失败: {}", e.getMessage());
            throw new UnauthorizedException("无效的 Token");
        }
    }

}
